﻿using DataService.Core.ServiceDTO;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;

namespace DataService.Core.ModeCode
{
    public class ModelCode
    {
        public static string _outPath { get; set; }
        private string _fullClassName { get; set; }

        /// <summary>
        /// 从数据库映射实体字段
        /// </summary>
        /// <param name="columnDataTable">来源 SELECT sobj.name as TableName,scol.name as ColumnName,sprop.[value] as Des,sc.name as TypeName,sc.length,scol.isnullable,scol.prec as ColumnLength,SCOM.text AS '默认值'  FROM syscolumns as scol inner join sys.sysobjects as sobj on scol.id=sobj.id and sobj.xtype='U' and sobj.name<>'dtproperties' inner join systypes as sc on sc.xusertype=scol.xtype left join sys.extended_properties as sprop on scol.id=sprop.major_id and scol.colid=sprop.minor_id LEFT JOIN syscomments SCOM ON scol.cdefault = SCOM.id</param>
        /// <param name="indexDataTable">来源 select COLUMN_NAME,t.TABLE_NAME from INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS i LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS t ON t.CONSTRAINT_NAME=i.CONSTRAINT_NAME WHERE t.CONSTRAINT_TYPE='PRIMARY KEY'</param>
        /// <param name="list"></param>
        ///   <param name="fullClassName">命名空间（Data.Model）</param>
        /// 
        public void GenerateModel(DataTable columnDataTable, DataTable indexDataTable, string outPath, string dbTypeName)
        {
            _fullClassName = $"Data.Model.{dbTypeName}";
            _outPath = outPath;
            //Console.WriteLine("-------------------------------------------开始输出-------------------------------------------");
            #region 读取数据库就绪准备
            //SqlConnection conn = new SqlConnection(sqlConnStr);
            //conn.Open();

            #region 生成DataTable
            //string sql = "SELECT sobj.name as TableName,scol.name as ColumnName,sprop.[value] as Des,sc.name as TypeName,sc.length,scol.isnullable,scol.prec as ColumnLength,SCOM.text AS '默认值'  FROM syscolumns as scol inner join sys.sysobjects as sobj on scol.id=sobj.id and sobj.xtype='U' and sobj.name<>'dtproperties' inner join systypes as sc on sc.xusertype=scol.xtype left join sys.extended_properties as sprop on scol.id=sprop.major_id and scol.colid=sprop.minor_id LEFT JOIN syscomments SCOM ON scol.cdefault = SCOM.id";
            //if (list != null && list.Count > 0)
            //{
            //    StringBuilder sbuilder = new StringBuilder();
            //    sbuilder.Append(" where sobj.name in (");
            //    foreach (string tableName in list)
            //    {
            //        sbuilder.Append("'").Append(tableName).Append("',");
            //    }
            //    string str = sbuilder.ToString().Substring(0, sbuilder.ToString().Length - 1);
            //    sql += str + ")";
            //}
            //SqlDataAdapter sda = new SqlDataAdapter(sql, conn);
            //sda.Fill(dt);
            #endregion


            #region 获取每张表的主键字段
            //string findSql = "select COLUMN_NAME,t.TABLE_NAME from INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS i LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS t ON t.CONSTRAINT_NAME=i.CONSTRAINT_NAME WHERE t.CONSTRAINT_TYPE='PRIMARY KEY'";
            //using (SqlDataAdapter pksda = new SqlDataAdapter(findSql, conn))
            //{
            //    pksda.Fill(PkDt);
            //}
            //conn.Dispose();//关闭数据库
            #endregion
            #endregion
            List<string> tableNameArray = new List<string>();
            #region 从数据库读取所有字段名称、字段类型、长度、是否为空、描述
            for (int i = 0; i < columnDataTable.Rows.Count; i++)
            {
                var read = columnDataTable.Rows[i];
                tableNameArray.Add(Convert.ToString(read["TableName"]));  //将表名保存到列表中
                // Console.WriteLine("表名：" + read["TableName"] + " 字段名称：" + read["ColName"] + " 字段描述：" + read["FieldDes"] + " 字段长度：" + read["length"] + " 字段类型：" + read["ColType"] + " 是否为空：" + read["IsNullable"]);
            }
            tableNameArray = tableNameArray.Distinct().ToList();
            int n = 0;
            foreach (string tableName in tableNameArray)
            {
                n = n + 1;
                DataRow[] dr = columnDataTable.Select("TableName='" + tableName + "'");
                DataRow[] indexRow = indexDataTable.Select("TableName='" + tableName + "'");
                ClassBuilder classBuilder = new ClassBuilder(_fullClassName, tableName, dr, indexRow, dbTypeName);
                //if (indexRow.Count() > 0)
                //{
                //    classBuilder.PkFiled = indexRow[0]["COLUMN_NAME"].ToString();
                //}
                classBuilder.Execute();
            }


            #endregion

            //  Console.WriteLine("-------------------------------------------完成-------------------------------------------");
        }
    }

    public class ClassBuilder
    {
        #region 属性
        /// <summary>写入器</summary>
        public StringBuilder StringBuilder = new StringBuilder();
        /// <summary>写入器</summary>
        public TextWriter TextWriter { get; set; }
        /// <summary>数据表</summary>
        public string TableName { get; set; }
        /// <summary>
        /// 每张表的主键字段
        /// </summary>
       // public string PkFiled { get; set; }
        /// <summary>命名空间</summary>
        public string Namespace { get; set; }
        /// <summary>数据行</summary>
        public DataRow[] DataRow { get; set; }

        /// <summary>索引</summary>
        public DataRow[] IndexDataRows { get; set; }
        /// <summary>引用命名空间</summary>
        public HashSet<string> Usings = new HashSet<string>(StringComparer.OrdinalIgnoreCase);


        /// <summary>纯净类</summary>
        public bool Pure { get; set; }


        /// <summary>生成接口</summary>
        public bool Interface { get; set; }


        /// <summary>基类</summary>
        public string BaseClass { get; set; }
        public int Indent = 5;//缩进
        public string IndetSpace { get; set; }//缩进空格
        #endregion
        private string _dbTypeName { get; set; }

        #region 构造
        /// <summary>实例化</summary>
        public ClassBuilder(string nameSpace, string tableName, DataRow[] dr, DataRow[] indexRows, string dbTypeName)
        {
            Namespace = nameSpace;
            TableName = tableName;
            DataRow = dr;
            IndexDataRows = indexRows;
            Usings.Add("System");
            Usings.Add("System.Collections.Generic");
            Usings.Add("System.ComponentModel");
            Usings.Add("DataService.Core.ModeCode");
            TextWriter = new StringWriter(StringBuilder); //实例化

            _dbTypeName = dbTypeName;
        }
        #endregion


        #region 主方法
        /// <summary>执行生成</summary>
        public virtual void Execute()
        {
            WriteLine("生成 {0}", TableName);
            //写入文件内容开始
            OnExecuting();
            //字段
            BuildItems();
            //文件内容末尾
            OnExecuted();
            //输出文件
            OutputFile();
        }


        /// <summary>生成头部</summary>
        protected virtual void OnExecuting()
        {
            // 引用命名空间
            var us = Usings.OrderBy(e => e.StartsWith("System") ? 0 : 1).ThenBy(e => e).ToArray();
            foreach (var item in us)
            {
                TextWriter.WriteLine("using {0};", item);
                // StringBuilder.Append("using {0};").Append(item);
            }
            TextWriter.WriteLine(); //命名空间和引用之间换行
            // TextWriter.WriteLine();
            if (!string.IsNullOrEmpty(Namespace))
            {
                TextWriter.WriteLine("namespace {0}", Namespace);
                TextWriter.WriteLine("{");
                //StringBuilder.Append("namespace ").Append(Namespace);   //命名空间
                //StringBuilder.Append("{");
            }
            BuildClassHeader();
        }


        /// <summary>实体类头部</summary>
        protected virtual void BuildClassHeader()
        {
            // 头部
            BuildAttribute();


            // 类名和基类
            var cn = GetClassName();
            if (!string.IsNullOrEmpty(BaseClass)) BaseClass = " : " + BaseClass;


            // 类接口
            if (Interface)
                WriteLine("public interface {0}{1}", cn, BaseClass);
            else
                WriteLine("public partial class {0}{1}", cn, BaseClass);
            WriteLine("{");
        }


        /// <summary>获取类名</summary>
        /// <returns></returns>
        protected virtual string GetClassName()
        {
            var name = TableName;
            if (Interface) name = "I" + name;


            return name;
        }


        /// <summary>获取基类</summary>
        /// <returns></returns>


        /// <summary>实体类头部</summary>
        protected virtual void BuildAttribute()
        {
            // 注释
            //  var des = Table.Description;
            // WriteLine("/// <summary>{0}</summary>", des);


            if (!Pure)
            {
                // WriteLine("[Serializable]");
                // WriteLine("[DataObject]");
                //  StringBuilder.Append("[Serializable]");
                // StringBuilder.Append("[DataObject]");
                SetIndent(3);//设置缩进空格
                TextWriter.WriteLine(_Indent + "[Serializable]");
                TextWriter.WriteLine(_Indent + "[DataObject]");
                // if (!des.IsNullOrEmpty()) WriteLine("[Description(\"{0}\")]", des);
            }
            TextWriter.WriteLine(_Indent + "public partial class {0}", TableName);
            TextWriter.WriteLine(_Indent + "{");
        }


        /// <summary>生成尾部</summary>
        protected virtual void OnExecuted()
        {
            // 类接口
            // WriteLine("}");
            // StringBuilder.Append("}");
            SetIndent(3);
            TextWriter.WriteLine(_Indent + "}");
            if (!string.IsNullOrEmpty(Namespace))
            {
                TextWriter.WriteLine("}");
                //StringBuilder.Append("}");
                //Writer.Write("}");
            }
        }


        /// <summary>生成主体</summary>
        protected virtual void BuildItems()
        {
            SetIndent(6);
            TextWriter.WriteLine(_Indent + "#region 属性");
            // StringBuilder.Append("#region 属性");
            // WriteLine("#region 属性");
            for (int i = 0; i < DataRow.Count(); i++)
            {
                if (i > 0) WriteLine();
                TextWriter.WriteLine("\r\n");
                string name = DataRow[i]["ColName"].ToString();
                BuildItem(DataRow[i]);
            }
            SetIndent(6);
            TextWriter.WriteLine(_Indent + "#endregion");
            // StringBuilder.Append("#endregion");
            //WriteLine("#endregion");
        }


        /// <summary>生成每一项</summary>
        protected virtual void BuildItem(DataRow dr)
        {
            // var dc = column;
            //BuildItemAttribute(column);
            // 注释
            // var des = dc.Description;
            // WriteLine("/// <summary>{0}</summary>", des);
            // StringBuilder.Append("/// <summary>").Append(Convert.ToString(dr["FieldDes"])).Append("</summary>");
            SetIndent(11);
            //这一行是 显示字段说明
            TextWriter.WriteLine(_Indent + "///<summary>{0}</summary>", Convert.ToString(dr["FieldDes"]).Replace("\r\n", ""));  //输出字段说明,同时替换换行符

            bool isNullAble = Convert.ToBoolean(dr["IsNullable"]); //0.不可为空 1.可为空
            string dbColumnType = Convert.ToString(dr["ColType"]);
            dbColumnType = dbColumnType.Replace(" ", "");
            //判断数据库类型

            string columnType = GetChangeType(dbColumnType);
            //定义的字符长度
            int.TryParse(dr["ValueLength"].ToString(), out int valueLength);
            //存储字节长度
            int.TryParse(dr["ColLength"].ToString(), out int colLength);

            string fieldName = dr["ColName"].ToString();

            string defaultValue = dr["DefaultValue"].ToString();
            string writerDefaultValue = string.Empty;
            if (!string.IsNullOrEmpty(defaultValue))
            {

                writerDefaultValue = _Indent + string.Format("[ColumnDefaultValue(\"{0}\")]", defaultValue);
            }

            //获取字段索引
            bool isIndexField = false;
            if (IndexDataRows != null && IndexDataRows.Length > 0)
            {

                for (int i = 0; i < IndexDataRows.Length; i++)
                {
                    if (IndexDataRows[i]["ColumnName"]?.ToString() == fieldName)
                    {
                        string indexName = IndexDataRows[i]["IndexName"].ToString();
                        isIndexField = true;


                        if ((bool)IndexDataRows[i]["PrimaryKey"])
                        {
                            TextWriter.WriteLine(_Indent + "[Fieldndex(\"PrimaryKey\",\"" + indexName + "\")]");
                            TextWriter.WriteLine(_Indent + string.Format("[ColumnProperty({0},\"{1}\",\"{2}\")]", valueLength, dbColumnType, Convert.ToString(dr["FieldDes"]).Replace("\r\n", "")));
                            break;
                        }
                        if ((bool)IndexDataRows[i]["UQIQUE"] && !(bool)IndexDataRows[i]["PrimaryKey"])
                        {
                            isIndexField = true;
                            TextWriter.WriteLine(_Indent + "[Fieldndex(\"Unique\",\"" + indexName + "\")]");
                            TextWriter.WriteLine(_Indent + string.Format("[ColumnProperty({0},\"{1}\",\"{2}\")]", valueLength, dbColumnType, Convert.ToString(dr["FieldDes"]).Replace("\r\n", "")));
                            break;
                        }
                        if (!(bool)IndexDataRows[i]["UQIQUE"] && !(bool)IndexDataRows[i]["PrimaryKey"])
                        {
                            isIndexField = true;
                            TextWriter.WriteLine(_Indent + "[Fieldndex(\"Index\",\"" + indexName + "\")]");
                            TextWriter.WriteLine(_Indent + string.Format("[ColumnProperty({0},\"{1}\",\"{2}\")]", valueLength, dbColumnType, Convert.ToString(dr["FieldDes"]).Replace("\r\n", "")));

                            break;
                        }
                    }
                }



            }

            if (isIndexField)
            {
               
                if (!string.IsNullOrEmpty(writerDefaultValue))
                {
                    TextWriter.WriteLine(writerDefaultValue);
                }
                TextWriter.WriteLine(_Indent + "public {0} {1} {2}", columnType, dr["ColName"], "{ get;set;}");  //主键属性
            }
            else
            {
                if (!isNullAble)
                {
                    TextWriter.WriteLine(_Indent + string.Format("[ColumnProperty({0},\"{1}\",\"{2}\")]", valueLength, dbColumnType, Convert.ToString(dr["FieldDes"]).Replace("\r\n", "")));
                    if (!string.IsNullOrEmpty(writerDefaultValue))
                    {
                        TextWriter.WriteLine(writerDefaultValue);
                    }
                    TextWriter.WriteLine(_Indent + "public {0} {1} {2}", columnType, dr["ColName"], "{ get; set;}");  //字段属性
                }
                else
                {
                    if (columnType != "String" && columnType != "byte[]")
                    {
                        TextWriter.WriteLine(_Indent + string.Format("[ColumnProperty({0},\"{1}\",\"{2}\")]", valueLength, dbColumnType, Convert.ToString(dr["FieldDes"]).Replace("\r\n", "")));
                        if (!string.IsNullOrEmpty(writerDefaultValue))
                        {
                            TextWriter.WriteLine(writerDefaultValue);
                        }
                        TextWriter.WriteLine(_Indent + "public {0}? {1} {2}", columnType, dr["ColName"], "{ get; set; }"); //字段属性
                    }
                    else
                    {
                        TextWriter.WriteLine(_Indent + string.Format("[ColumnProperty({0},\"{1}\",\"{2}\")]", valueLength, dbColumnType, Convert.ToString(dr["FieldDes"]).Replace("\r\n", "")));
                        if (!string.IsNullOrEmpty(writerDefaultValue))
                        {
                            TextWriter.WriteLine(writerDefaultValue);
                        }
                        TextWriter.WriteLine(_Indent + "public {0} {1} {2}", columnType, dr["ColName"], "{ get; set; }"); //字段属性
                    }

                    // StringBuilder.Append("      public   ").Append(type).Append("?").Append("{ get; set; }");
                }
            }







            //if (!Pure)
            //{
            //    if (!des.IsNullOrEmpty()) WriteLine("[Description(\"{0}\")]", des);


            //    var dis = dc.DisplayName;
            //    if (!dis.IsNullOrEmpty()) WriteLine("[DisplayName(\"{0}\")]", dis);
            //}


            //var type = dc.Properties["Type"];
            //if (type.IsNullOrEmpty()) type = dc.DataType?.Name;


            //if (Interface)
            //    WriteLine("{0} {1} {{ get; set; }}", type, dc.Name);
            //else
            //    WriteLine("public {0} {1} {{ get; set; }}", type, dc.Name);
        }


        ///// <summary>属性头部特性</summary>
        //protected virtual void BuildItemAttribute(IDataColumn column)
        //{
        //    // 注释
        //    var des = column.Description;
        //    WriteLine("/// <summary>{0}</summary>", des);
        //    if (!des.IsNullOrEmpty()) WriteLine("[Description(\"{0}\")]", des);


        //    WriteLine("[Serializable]");
        //    WriteLine("[DataObject]");
        //}
        #endregion


        #region 写入缩进方法
        private string _Indent;


        /// <summary>设置缩进</summary>
        /// <param name="add"></param>
        protected virtual void SetIndent(int indentNumber)
        {
            _Indent = "               ";
            if (indentNumber <= 15) //空格长度为15
            {
                _Indent = _Indent.Substring(0, indentNumber);
            }
            else
            {
                _Indent = "";
            }
        }


        /// <summary>写入</summary>
        /// <param name="value"></param>
        protected virtual void WriteLine(string value = null)
        {
            if (string.IsNullOrEmpty(value))
            {
                // Writer.WriteLine();
                return;
            }
            var v = value;
            if (!string.IsNullOrEmpty(_Indent)) v = _Indent + v;


            //  Writer.WriteLine(v);
        }


        /// <summary>写入</summary>
        /// <param name="format"></param>
        /// <param name="args"></param>
        protected virtual void WriteLine(string format, params object[] args)
        {
            if (!string.IsNullOrEmpty(_Indent)) format = _Indent + format;


            // Writer.WriteLine(format, args);
        }


        /// <summary>清空，重新生成</summary>
        public void Clear()
        {
            _Indent = null;


            //var sw = Writer as StringWriter;
            //if (sw != null)
            //{
            //    sw.GetStringBuilder().Clear();
            //}
        }


        /// <summary>输出结果</summary>
        /// <returns></returns>
        //public override String ToString()
        //{
        //    return Writer.ToString();
        //}
        #endregion


        #region 保存
        /// <summary>输出目录</summary>
        public string Output { get; set; }


        /// <summary>保存文件，返回文件路径</summary>
        public virtual void OutputFile(string ext = null, bool overwrite = true)
        {
            BuilderHelp pathBuilder = new BuilderHelp();

            string dirName = Path.GetDirectoryName(pathBuilder.Path);
            if (!Directory.Exists(dirName))
            {
                Directory.CreateDirectory(dirName);
            }
            string path = pathBuilder.Path + TableName + pathBuilder.Suffix;
            //if (!File.Exists(path)) //文件存在,先清除内容
            //{
            using (StreamWriter tw = new StreamWriter(path))  //如果原文件已存在,则会覆盖原文件内容
            {
                tw.WriteLine(StringBuilder.ToString());
                // Console.WriteLine(tw.BaseStream.GetType());     //输出FileStream
            }
            //}
            //var p = Output;
            ////if (Table.Properties.ContainsKey("Output")) p = p.CombinePath(Table.Properties["Output"]);
            ////if (Table.Properties.ContainsKey("分类")) p = p.CombinePath(Table.Properties["分类"]);


            //if (ext.IsNullOrEmpty()) ext = ".cs";


            //if (Interface)
            //    p = p.CombinePath("I" + Table.Name + ext);
            //else if (!Table.DisplayName.IsNullOrEmpty())
            //    p = p.CombinePath(Table.DisplayName + ext);
            //else
            //    p = p.CombinePath(Table.Name + ext);


            //p = p.GetFullPath();


            //if (!File.Exists(p) || overwrite) File.WriteAllText(p.EnsureDirectory(true), ToString());


            //return p;
        }
        #endregion


        #region 辅助
        /// <summary>C#版本</summary>
        public Version CSharp { get; set; }


        /// <summary>nameof</summary>
        /// <param name="name"></param>
        /// <returns></returns>
        //protected String NameOf(String name)
        //{
        //    var v = CSharp;
        //    if (v == null || v.Major == 0 || v.Major > 5) return "nameof({0})".F(name);


        //    return "\"" + name + "\"";
        //}


        /// <summary>是否调试</summary>
        public static bool Debug { get; set; }






        /// <summary>写日志</summary>
        /// <param name="format"></param>
        /// <param name="args"></param>
        //public void WriteLog(String format, params Object[] args)
        //{
        //    Log?.Info(format, args);
        //}
        #endregion


        private string GetChangeType(string type)
        {
            //这里没做程序设计； 可以使用抽象类进行优化程序设计；先这么处理 ，以后再优化

            //默认为sqlserver数据库，数据类型
            DataBaseTypes dataBaseTypes = new SqlserverBaseTypes();
            if (_dbTypeName == DatabaseType.SQLite.ToString())
            {
                dataBaseTypes = new SqliteBaseTypes();
            }
            if (_dbTypeName == DatabaseType.SqlServer.ToString())
            {
                dataBaseTypes = new SqlserverBaseTypes();
            }
            if (_dbTypeName == DatabaseType.MySql.ToString())
            {
                dataBaseTypes = new MysqlBaseTypes();
            }
            if (_dbTypeName == DatabaseType.Oracle.ToString())
            {
                dataBaseTypes = new OracleBaseTypes();
            }
            if (_dbTypeName == DatabaseType.DaMeng.ToString())
            {
                dataBaseTypes = new DMBaseTypes();
            }

            var dataTypes = dataBaseTypes._DataTypes;
            foreach (var item in dataTypes)
            {
                bool isSuccess = item.Value.Any(x => x.ToLower() == type.ToLower());
                if (isSuccess)
                {
                    return item.Key.Name;
                }
            }
            return typeof(String).Name;
        }


    }

    public class BuilderHelp
    {
        /// <summary> 输出路径 </summary>
        public string Path { get { return ModelCode._outPath; } }
        /// <summary> 输出文件后缀</summary>
        public string Suffix { get { return ".cs"; } }
    }

    #region 数据库类型
    public abstract class DataBaseTypes
    {
        public abstract Dictionary<Type, String[]> _DataTypes { get; }
    }
    public class SqlserverBaseTypes : DataBaseTypes
    {
        public override Dictionary<Type, String[]> _DataTypes
        {
            get
            {

                return new Dictionary<Type, String[]>(){
            { typeof(Byte[]), new String[] { "binary", "image", "varbinary"} },
            { typeof(Guid), new String[] { "uniqueidentifier" } },
            { typeof(Boolean), new String[] { "bit" } },
            { typeof(Byte), new String[] { "tinyint" } },
            { typeof(Int16), new String[] { "smallint" } },
            { typeof(Int32), new String[] { "int" } },
            { typeof(Int64), new String[] { "bigint" } },
            { typeof(Single), new String[] { "real" } },
            { typeof(Double), new String[] { "float", "double" } },
            { typeof(Decimal), new String[] { "money", "decimal", "numeric", "smallmoney" } },
            { typeof(DateTime), new String[] { "datetime", "smalldatetime", "datetime2", "date", "timestamp","time" } },
            { typeof(String), new String[] { "nvarchar", "ntext", "text", "varchar", "char", "nchar", "xml" } }
        };

            }
        }
    }
    public class SqliteBaseTypes : DataBaseTypes
    {
        public override Dictionary<Type, String[]> _DataTypes
        {
            get
            {

                return new Dictionary<Type, String[]>
                    {
                    { typeof(Byte[]), new String[] { "binary", "varbinary", "blob", "image", "general", "oleobject" }},
                    { typeof(Boolean), new String[] { "bit", "yesno", "logical", "bool", "boolean" } },
                    { typeof(Byte), new String[] { "tinyint" } },
                    { typeof(Int16), new String[] { "smallint" } },
                    { typeof(Int32), new String[] { "int" } },
                    { typeof(Int64), new String[] { "integer", "counter", "autoincrement", "identity", "long", "bigint" } },
                    { typeof(Single), new String[] { "single" } },
                    { typeof(Double), new String[] { "real", "float", "double" } },
                    { typeof(Decimal), new String[] { "money", "decimal", "currency", "numeric" } },
                    { typeof(DateTime), new String[] { "datetime", "smalldate", "timestamp", "date", "time" } },
                    { typeof(String), new String[] { "nvarchar", "ntext", "varchar", "memo", "longtext", "note", "text", "string", "char", "char", "uniqueidentifier", "guid" } }
                   };

            }
        }
    }




    public class MysqlBaseTypes : DataBaseTypes
    {
        public override Dictionary<Type, String[]> _DataTypes
        {
            get
            {

                return new Dictionary<Type, String[]>()
        {
            { typeof(Byte[]), new String[] { "BLOB", "TINYBLOB", "MEDIUMBLOB", "LONGBLOB", "binary", "varbinary", "image" } },

            { typeof(Byte), new String[] { "tinyint" } },
            { typeof(SByte), new String[] {"tinyint unsigned" } },
            { typeof(Int16), new String[] { "smallint"} },
            { typeof(UInt16), new String[] { "smallint unsigned" } },
            { typeof(Int32), new String[] { "int", "YEAR", "MEDIUMINT", "MEDIUMINT UNSIGNED" } },
            { typeof(UInt32), new String[] { "int unsigned"} },
            { typeof(Int64), new String[] { "bigint"} },
            { typeof(UInt64), new String[] { "bigint unsigned"} },
            { typeof(Single), new String[] { "float" } },
            { typeof(Double), new String[] { "double" } },
            { typeof(Decimal), new String[] { "numeric", "smallmoney", "decimal", "money" } },
            { typeof(DateTime), new String[] { "smalldatetime", "date", "datetime", "time", "timestamp" } },
            // mysql中nvarchar会变成utf8字符集的varchar，而不会取数据库的utf8mb4
            { typeof(String), new String[] { "VARCHAR", "LONGTEXT", "TEXT", "CHAR", "NCHAR", "NVARCHAR", "SET", "ENUM", "TINYTEXT", "TEXT", "MEDIUMTEXT" } },
            { typeof(Boolean), new String[] {"bit" } },
            { typeof(Guid), new String[] { "guid" } },
        };

            }
        }
    }
    public class OracleBaseTypes : DataBaseTypes
    {
        public override Dictionary<Type, String[]> _DataTypes
        {
            get
            {

                return new Dictionary<Type, String[]>()
        {
            { typeof(Byte[]), new String[] { "RAW({0})", "BFILE", "BLOB", "LONG RAW" } },
            { typeof(Boolean), new String[] { "NUMBER(1,0)" } },
            { typeof(Byte), new String[] { "NUMBER(1,0)" } },
            { typeof(Int16), new String[] { "NUMBER(5,0)" } },
            { typeof(Int32), new String[] { "NUMBER(10,0)" } },
            { typeof(Int64), new String[] { "NUMBER(20,0)" } },
            { typeof(Single), new String[] { "BINARY_FLOAT" } },
            { typeof(Double), new String[] { "BINARY_DOUBLE" } },
            { typeof(Decimal), new String[] { "NUMBER", "FLOAT" } },
            { typeof(DateTime), new String[] { "DATE", "TIMESTAMP", "TIMESTAMP", "TIMESTAMP" } },
            { typeof(String), new String[] { "VARCHAR2", "NVARCHAR2", "LONG", "CHAR", "CLOB", "NCHAR", "NCLOB", "XMLTYPE", "ROWID" } }
        };

            }
        }
    }

    public class DMBaseTypes : DataBaseTypes
    {

        public override Dictionary<Type, String[]> _DataTypes
        {
            get
            {

                return new Dictionary<Type, String[]>(){
            { typeof(Boolean), new String[] { "BIT" } },
            { typeof(SByte), new String[] { "TINYINT", "BYTE" } },
            { typeof(Int16), new String[] { "SMALLINT" } },
            { typeof(Int32), new String[] { "INT", "INTEGER", "PLS_INTEGER" } },
            { typeof(Int64), new String[] { "BIGINT" } },
            { typeof(Single), new String[] { "REAL", "FLOAT" } },
            { typeof(Double), new String[] { "DOUBLE" } },
            { typeof(Decimal), new String[] { "DEC", "NUMERIC", "DECIMAL" } },
            { typeof(DateTime), new String[] { "DATE", "TIME", "TIMESTAMP", "DATETIME" } },
            { typeof(String), new String[] { "CHAR", "VARCHAR", "TEXT", "LONGVARCHAR" } },
            { typeof(Byte[]), new String[] {  "BINARY", "VARBINARY", "BLOB", "IMAGE", "LONGVARBINARY" } },
            { typeof(object), new String[] { "CLOB", "BFILE" } }

        };

            }
        }
    }

    #endregion
}
